export function patch(oldNode, vnode){
  // 将vnode转化成真实dom
  if (oldNode.nodeType === 1) {
    // 第一次直接进行替换
    let el = createEl(vnode);
    // 替换
    let parentEl = oldNode.parentNode;
    parentEl.insertBefore(el, oldNode.nextsibling);
    parentEl.removeChild(oldNode);
    return el
  } else {
    // diff算法
    if (oldNode.tag !== vnode.tag) {
      oldNode.el.parentNode.replaceChild(createEl(vnode), oldNode.el);
    }
    if (!oldNode.tag) {
      if (oldNode.text !== vnode.text) {
        return oldNode.el.textContent = vnode.text
      }
    }
    let el = vnode.el = oldNode.el;
    updateProps(vnode, oldNode.data);
    let oldChildren = oldNode.children || [];
    let newChildren = vnode.children || [];
    if (oldChildren.length > 0 && newChildren.length > 0) {
      // 两个都有子元素
      updateChild(oldChildren, newChildren);
    } else if (oldChildren.length > 0) {
      // 老的有，新的没有
      el.innerHTML = '';
    } else if (newChildren.length > 0) {
      // 新的有，老的没有
      for(let i = 0; i < newChildren.length; i++) {
        let child = newChildren[i];
        el.appendChild(createEl(child));
      }
    }
    return el
  }
}

function updateProps(vnode, oldProps = {}){
  let newProps = vnode.data || {};
  let el = vnode.el;
  // 老的有属性，新的没有
  for(let key in oldProps) {
    if (!newProps[key]) {
      el.removeAttribute[key];
    }
  }
  
  let newStyle = newProps.style || {};
  let oldStyle = oldProps.style || {};
  for(let key in oldStyle) {
    if (!newStyle[key]) {
      el.style = ''
    }
  }
  for(let key in newProps) {
    if (key === 'style') {
      for(let name in newStyle) {
        el.style[name] = newProps.style[name];
      }
    } else if (key === 'class') {
      el.className = newProps.class
    } else {
      el.setAttribute(key, newProps[key])
    }
  }
}
function isSameVnode(oldContent, newContent){
  return (oldContent.tag === newContent.tag) && (oldContent.key === newContent.key)
}

function updateChild(oldChildren, newChildren){
//  vue diff算法
// dom中的操作元素， 头部添加、尾部添加、倒叙和正序添加
// 同层遍历，广度优先；
  let oldStartIndex = 0; // 老的开始索引
  let oldStartVnode = oldChildren[oldStartIndex]; // 老的开始元素
  let oldEndIndex = oldChildren.length - 1; // 老的结束索引
  let oldEndVnode = oldChildren[oldEndIndex]; // 老的最后元素

  let newStartIndex = 0; // 新的开始索引
  let newStartVnode = newChildren[newStartIndex]; // 新的开始元素
  let newEndIndex = newChildren.length - 1; // 新的结束索引
  let newEndVnode = newChildren[newEndIndex]; // 新的最后元素

  // 创建旧元素的映射表
  function makeIndexByKey(children){
    let map = {};
    children.forEach((item, index) => {
      if (item.key) {
        map[item.key] = index;
      }
    })
    return map
  }
  let map = makeIndexByKey(oldChildren);
  while (oldStartIndex <= oldEndIndex && newStartIndex <= newEndIndex) {
    if (isSameVnode(oldStartVnode, newStartVnode)) {
      patch(oldStartVnode, newStartVnode);
      oldStartVnode = oldChildren[++oldStartIndex];
      newStartVnode = newChildren[++newStartIndex];
    } else if (isSameVnode(oldEndVnode, newEndVnode)) {
      patch(oldEndVnode, newEndVnode);
      oldEndVnode = oldChildren[--oldEndIndex];
      newEndVnode = newChildren[--newEndIndex];
    } else if (isSameVnode(oldStartVnode, newEndVnode)) {
      patch(oldStartVnode, newEndVnode);
      oldStartVnode = oldChildren[++oldStartIndex];
      newEndVnode = newChildren[--newEndIndex];
    } else if (isSameVnode(oldEndVnode, newStartVnode)) {
      patch(oldEndVnode, newStartVnode);
      oldEndVnode = oldChildren[--oldEndIndex];
      newStartVnode = newChildren[++newStartIndex];
    } else {
      // 暴力比对
      const parent = oldEndVnode.parentNode;
      let moveIndex = map[newStartVnode.key];
      if (moveIndex === undefined) {
        parent.insertBefore[createEl(newStartVnode), oldEndVnode.el]
      } else {
        let moveVnode = oldChildren[moveIndex];
        oldChildren[moveIndex] = null;
        parent.insertBefore(moveVnode.el, oldStartVnode.el);
        patch(moveVnode, newStartVnode);
        // 缺少删除
      }
      newStartVnode = newChildren[++newStartIndex];
    }
  }
}
export function createEl(vnode){
  let {tag, data, key, children, text} = vnode;
  if (typeof tag === 'string') {
    const el = vnode.el = document.createElement(tag);
    if (children.length > 0) {
      children.forEach(child => {
        vnode.el.appendChild(createEl(child));
      })
    }
    for(let key in data) {
      if (key === 'style') {
        for(let name in data[key]) {
          el.style[name] = data.style[name];
        }
      } else if (key === 'class') {
        el.className = data.class
      } else {
        el.setAttribute(key, data[key])
      }
    }
    el.key = key;
  } else {
    vnode.el = document.createTextNode(text);
  }
  return vnode.el
}